#include <fstream>
#include <iostream>

#include "wave_reader.h"

WaveReader::WaveReaderPtr WaveReader::ins;

WaveReader::WaveReader(const std::string &wavePath)
{
  Init(wavePath);
  short *dt = (short*)data.data;
  for (unsigned i = 0; i < data.size / 2; ++i)
  {
    buff.push_back(dt[i]);
  }
}

bool WaveReader::Init(const std::string &wavePath)
{
  std::ifstream waveFile;

  //std::clog << "Loading file..." << std::endl;
  waveFile.open(wavePath.c_str(), 
    std::ios::beg | std::ios::in | std::ios::binary);
  if (!waveFile)
  {
    std::clog << "File not found!" << std::endl;
    return false;
  }

  //std::clog << "Find chunk RIFF..." << std::endl;
  DWORD dwRiff = 0;
  waveFile.read((char*)&dwRiff, 4);
  if (dwRiff != MAKEFOURCC('R', 'I', 'F', 'F'))
  {
    std::clog << "Can't find chunk RIFF\nUnsupported file format!" << std::endl;
    return false;
  }
  riff.id = dwRiff;

  DWORD dwRiffSize = 0;
  waveFile.read((char*)&dwRiffSize, 4);
  riff.size = dwRiffSize;

  //////////////////////////////////////////////////////////////////////////

  //std::clog << "Find chunk WAVE..." << std::endl;
  DWORD dwWave = 0;
  waveFile.read((char*)&dwWave, 4);
  if (dwWave != MAKEFOURCC('W', 'A', 'V', 'E'))
  {
    std::clog << "Can't find chunk WAVE\nUnsupported file format!" << std::endl;
    return false;
  }
  wave.wave_id = dwWave;

  //std::clog << "Find chunk fmt..." << std::endl;
  DWORD dwFmt = 0;
  waveFile.read((char*)&dwFmt, 4);
  if (dwFmt != MAKEFOURCC('f', 'm', 't', ' '))
  {
    std::clog << "Can't find chunk fmt\nUnsupported file format!" << std::endl;
    return false;
  }
  wave.fmt_id = dwFmt;

  //std::clog << "Find info about audio..." << std::endl;
  long lSizeFmt = 0;
  waveFile.read((char*)&lSizeFmt, 4);
  if (lSizeFmt == 0)
  {
    std::clog << "Can't find size of audio indo\n\
                 Unsupported file format!" << std::endl;
    return false;
  }
  wave.size = lSizeFmt;

  //std::clog << "Info size: " << lSizeFmt << std::endl;
  WAVEFORMATEX waveFormat = WAVEFORMATEX();
  waveFile.read((char*)&waveFormat, 16);
  waveFile.ignore(lSizeFmt - 16);
  wave.desc = waveFormat;

  if (waveFormat.wFormatTag != 1)
  {
    std::clog << "This file is compressed!" << std::endl;
    std::clog << "Unsupported file format!" << std::endl;
    return false;
  }

  //////////////////////////////////////////////////////////////////////////

  DWORD dwNextChunk = 0;
  waveFile.read((char*)&dwNextChunk, 4);
  if (dwNextChunk == MAKEFOURCC('f', 'a', 'c', 't'))
  {
    DWORD dwSizeFact = 0;
    waveFile.read((char*)&dwSizeFact, 4);
    waveFile.ignore(dwSizeFact);
    waveFile.read((char*)&dwNextChunk, 4);
    std::clog << "Chunk fact skipped!" << std::endl;
  }

  //std::clog << "Find chunk DATA..." << std::endl;
  if (dwNextChunk != MAKEFOURCC('d', 'a', 't', 'a'))
  {
    std::clog << "Can't find chunk DATA\n" << std::endl;
    std::clog << "Unsupported file format!" << std::endl;
    return false;
  }
  data.id = dwNextChunk;

  DWORD dwDataSize = 0;
  waveFile.read((char*)&dwDataSize, 4);
  data.size = dwDataSize;
  if (dwDataSize == 0)
  {
    std::clog << "No audio data..." << std::endl;
    return false;
  }
  //std::clog << "Audio size: " << dwDataSize<< " bytes" << std::endl;

  char *pData = new char[dwDataSize];
  waveFile.read(pData, dwDataSize);
  data.data = pData;
  //std::clog << "Closing file..." << std::endl;
  waveFile.close();

  return true;
}